package com.andatsoft.laisim.asynctask;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Random;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;

import com.andatsoft.laisim.R;
import com.andatsoft.laisim.db.DataBaseAccess;
import com.andatsoft.laisim.entity.Song;
import com.andatsoft.laisim.utils.Common;

public class AlbumArtGettingTask extends AsyncTask<Integer, Void, Integer> {

	private Context mContext;

	public AlbumArtGettingTask(Context c) {
		this.mContext = c;
	}

	@Override
	protected Integer doInBackground(Integer... params) {
		SharedPreferences sp = mContext.getSharedPreferences(
				Common.SP_ALBUM_ART_SETTING_NAME, Context.MODE_PRIVATE);
		boolean isDown = sp.getBoolean(Common.SP_ALBUM_ART_IS_DOWNLOAD, false);
		if (!isDown) {
			return 0;
		}
		int songId = params[0];
		DataBaseAccess db = DataBaseAccess.getInstance(mContext
				.getApplicationContext());
		if (songId == -1) {
			// down load all
			List<Song> lS = db.getAllSong();
			if (lS.size() > 0) {
				for (Song s : lS) {
					if (s != null) {
						int nextImg = db.getNextAlbumIndexForSearching(s
								.getId() + "");
						int re = searchAndDownAlbumArt(s, nextImg);
						if (re == 0) {
							// stop down load when current network not wifi
							return 1;
						} else if (re == -1) {
							return 2;
						}

					}
				}
			}
		} else {
			Song s = db.getSong(songId);
			if (s != null) {
				int nextImg = db.getNextAlbumIndexForSearching(s.getId() + "");
				int re = searchAndDownAlbumArt(s, nextImg);
				if (re == 0) {
					// stop down load when current network not wifi
					return 1;
				} else if (re == -1) {
					return 2;
				}
			}
		}
		return 3;
	}

	private int searchAndDownAlbumArt(Song s, int indexImg) {
		// check if user want to down load the high quality album
		SharedPreferences sp = mContext.getSharedPreferences(
				Common.SP_ALBUM_ART_SETTING_NAME, Context.MODE_PRIVATE);
		boolean isHighQ = sp.getBoolean(
				Common.SP_ALBUM_ART_IS_DOWNLOAD_HIGH_QUALITY, false);
		boolean isWifiOnly = sp.getBoolean(
				Common.SP_ALBUM_ART_IS_DOWNLOAD_WIFI_ONLY, false);
		if (isWifiOnly) {
			// check if the current network type is wifi
			// if the current network type is not wifi. return.
			if (!isNetworkWifi())
				return 0;
		}
		String songTitle = s.getTitle();
		songTitle = songTitle.replace(" ", "+");
		// String songAlbum = s.getAlbum();
		// if (songAlbum.equals(mContext
		// .getString(R.string.common_text_unknown_song_info)))
		// songAlbum = "";
		// songAlbum = songAlbum.replace(" ", "+");

		String songArtist = s.getArtist();
		if (songArtist.equals(mContext
				.getString(R.string.common_text_unknown_song_info)))
			songArtist = "";
		songArtist = songArtist.replace(" ", "+");
		String src = "https://images.search.yahoo.com/search/images?p=Album+"
				+ songTitle + "+" + songArtist;
		Log.i("ALbumart..", src + "");

		try {
			URL url = new URL(src);
			HtmlCleaner html = new HtmlCleaner();
			CleanerProperties props = html.getProperties();
			props.setAllowHtmlInsideAttributes(true);
			props.setAllowMultiWordAttributes(true);
			props.setRecognizeUnicodeChars(true);
			props.setOmitComments(true);

			TagNode node = html.clean(url);
			String imgLink = null;
			if (!isHighQ) {
				String xPathExpression = "//li[@class='ld']/a/img";

				Object[] obj = node.evaluateXPath(xPathExpression);
				// get the first result

				if (obj == null || obj.length <= 0) {

					return -1;
				}
				if (indexImg > obj.length - 1) {
					if (obj.length == 1) {
						indexImg = 0;
					} else {
						indexImg = new Random().nextInt(obj.length - 1);
					}
				}
				TagNode imgNode = (TagNode) obj[indexImg];
				imgLink = imgNode.getAttributeByName("src");
				if (imgLink == null)
					return -1;
				imgLink = imgLink.substring(0, imgLink.indexOf("&"));
			} else {
				String xPathExpression = "//li[@class='ld']/a";

				Object[] obj = node.evaluateXPath(xPathExpression);
				// get the first result
				if (obj == null || obj.length <= 0)
					return -1;
				if (indexImg > obj.length - 1) {
					if (obj.length == 1) {
						indexImg = 0;
					} else {
						indexImg = new Random().nextInt(obj.length - 1);
					}

				}
				TagNode aNode = (TagNode) obj[indexImg];
				imgLink = aNode.getAttributeByName("href");
				if (imgLink == null)
					return -1;
				// extract original image link from ahref link
				imgLink = imgLink.substring(imgLink.indexOf("&imgurl") + 8,
						imgLink.indexOf("&rurl"));
				imgLink = encodeImgURL(imgLink);
				// clean new link
				// url = new URL(imgLink);
				// TagNode newNode = html.clean(url);
				// xPathExpression = "//img";
				// obj = newNode.evaluateXPath(xPathExpression);
				// if (obj == null || obj.length <= 0)
				// return 1;
				// aNode = (TagNode) obj[0];
				// imgLink = aNode.getAttributeByName("src");
				Log.d("linkimg", imgLink + "");

			}
			Log.d("linkimg", imgLink + "");
			downloadAlbumArt(imgLink, s.getId());
		} catch (MalformedURLException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		} catch (XPatherException e) {

			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 1;
	}

	private String encodeImgURL(String src) {
		if (!src.startsWith("http://"))
			src = "http://" + src;
		String result = src.replace("%2F", "/");
		return result;
	}

	private boolean isNetworkWifi() {
		ConnectivityManager cn = (ConnectivityManager) mContext
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo netWifi = cn.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		if (netWifi.isConnected())
			return true;
		return false;
	}

	/**
	 * Download the image
	 * 
	 * @return
	 */
	public void downloadAlbumArt(String imageLink, int songId) {
		// initialize the default HTTP client object
		HttpClient client = null;

		// forming a HttoGet request
		HttpGet getRequest = null;
		try {
			client = new DefaultHttpClient();

			getRequest = new HttpGet(imageLink);
			HttpResponse response = client.execute(getRequest);

			// check 200 OK for success
			final int statusCode = response.getStatusLine().getStatusCode();

			if (statusCode != HttpStatus.SC_OK) {
				return;
			}
			final HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream inputStream = null;
				try {
					inputStream = entity.getContent();

					int MAX_SIZE = 1280;
					// Decode image size to the dimension of the image
					BitmapFactory.Options o = new BitmapFactory.Options();
					o.inJustDecodeBounds = true;
					BitmapFactory.decodeStream(inputStream, null, o);
					inputStream.close();

					int scale = 1;
					if (o.outHeight > MAX_SIZE || o.outWidth > MAX_SIZE) {
						scale = (int) Math.pow(
								2,
								(int) Math.ceil(Math.log(MAX_SIZE
										/ (double) Math.max(o.outHeight,
												o.outWidth))
										/ Math.log(0.5)));
					}
					// Decode with inSampleSize
					BitmapFactory.Options o2 = new BitmapFactory.Options();
					o2.inSampleSize = scale;
					o2.inJustDecodeBounds = false;
					// recreate input stream
					inputStream = getInputStremFromUrl(getRequest);
					Bitmap bitmap = BitmapFactory.decodeStream(inputStream,
							null, o2);
					if (inputStream != null)
						inputStream.close();

					saveAlbumArt(bitmap, songId);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if (inputStream != null) {
						inputStream.close();
					}
					entity.consumeContent();
				}
			}
		} catch (HttpHostConnectException e) {
			getRequest.abort();
			Log.e("ERROR_ImageDownloader", e.getMessage());
		} catch (Exception e) {
			// IOException
			getRequest.abort();
			e.printStackTrace();
		}
	}

	private InputStream getInputStremFromUrl(HttpGet url) {
		// initialize the default HTTP client object
		HttpClient client = null;
		try {
			client = new DefaultHttpClient();
			HttpResponse response = client.execute(url);

			// check 200 OK for success
			final int statusCode = response.getStatusLine().getStatusCode();

			if (statusCode != HttpStatus.SC_OK) {
				Log.w("INFO_ImageDownloader", "Error: " + statusCode);
				return null;
			}
			return response.getEntity().getContent();
		} catch (Exception e) {
			Log.e("ERROR:", e.getMessage());
			e.printStackTrace();
			return null;
		}

	}

	private void saveAlbumArt(Bitmap imageData, int songId) {
		if (imageData == null) {
			// some error when downloading image
			// update image index to load other image
			DataBaseAccess db = DataBaseAccess.getInstance(mContext
					.getApplicationContext());
			db.updateAlbumArtIndex(songId + "");
			return;
		}
		// get path to external storage (SD card)
		String path = Environment.getExternalStorageDirectory()
				+ "/Laisim/AlbumArt/";
		File sdIconStorageDir = new File(path);

		if (!sdIconStorageDir.isDirectory()) {
			// create storage directories, if they don't exist
			sdIconStorageDir.mkdirs();
		}
		try {
			String imgPath = path + songId;
			FileOutputStream fileOutputStream = new FileOutputStream(imgPath);

			BufferedOutputStream bos = new BufferedOutputStream(
					fileOutputStream);
			imageData.compress(CompressFormat.PNG, 100, bos);

			bos.flush();
			bos.close();
			saveToDB(songId, imgPath);

		} catch (FileNotFoundException e) {
			Log.w("INFO", "Error saving image file: " + e.getMessage());

		} catch (IOException e) {
			Log.w("INFO", "Error saving image file: " + e.getMessage());

		}
	}

	private void saveToDB(int songId, String address) {
		DataBaseAccess db = DataBaseAccess.getInstance(mContext
				.getApplicationContext());
		db.addAlbumArt(songId + "", address);
	}

}
